#include "voltagemeasure.h"
#include "bllcontroller.h"
#include "globaldef.h"
#include "bllchartreader.h"
#include "datacenter.h"
#include "controlcenter.h"
#include "ivdsmeasure.h"
#include "measureworker.h"
#include "vdsconfig.h"
#include "userlogger.h"
#include "logger.h"
#include <QThread>
#include <QDebug>
#include <QMutex>
#include <QWaitCondition>

#define VOLTAGE_PULSE_INTERVAL 1000
#define VOLTAGE_TESTING_TIMES 60000
#define VOLTAGE_RECOVERT_TIMES 60000

class VdsMeasure : public IVdsMeasure {};

class VoltageMeasurePrivate : public QThread
{
    Q_OBJECT
public:
    enum VoltageType { Low, Medium, High };
    VoltageMeasurePrivate() { initComponent(); }
    void start(VoltTest *data);
    void stop();

signals:
    void progress(const QString &info, bool stopped = false);

private slots:
    void onMeasureResult(double voltage, double pulseWidth);
    void onCommRespond(const HostReply &info);
    void onMeasureError(bool stopTest);

protected:
    void run() Q_DECL_OVERRIDE;

private:
    void initComponent();
    void createComponent();
    void destoryComponent();
    void stopComponent();
    void startComponent(int voltage, int pulseWidth, int pulseInterval);
    void setVdsParameter(int voltage, int pulseWidth, int pulseInterval);
    void startTest(int voltage, int pulseWidth, int pulseInterval = VOLTAGE_PULSE_INTERVAL);

private:
    VoltTest *m_voltTest;
    QWaitCondition m_condition;
    QMutex m_mutex;
    VdsMeasure m_vds;
    VoltageType m_type;
};

VoltageMeasure::VoltageMeasure(QObject *parent) : IMeasure(parent), d(new VoltageMeasurePrivate)
{
    connect(d, &VoltageMeasurePrivate::progress, this, &IMeasure::progress);
}

VoltageMeasure::~VoltageMeasure()
{
    d->stop();
    d->disconnect();
    d->deleteLater();
}

void VoltageMeasure::measure(IMeasureData *data)
{
    emit d->start(static_cast<VoltTest *>(data));
}

void VoltageMeasurePrivate::start(VoltTest *data)
{
    if (isRunning())
    {
        sysError("Error: VoltageMeasure running, cannot start agin.");
        return;
    }

    m_type = Low;
    m_voltTest = data;
    QThread::start();
}

void VoltageMeasurePrivate::stop()
{// 主动停止测试
    requestInterruption();
    m_condition.wakeAll();
    quit();
    wait();
}

void VoltageMeasurePrivate::startTest(int voltage, int pulseWidth, int pulseInterval)
{
    bool componentStarted = false;
    bool voltMeasureStarted = false;

    if (!isInterruptionRequested())
    {// 启动测量组件
        QMutexLocker locker(&m_mutex);
        startComponent(voltage, pulseWidth, pulseInterval);
        m_condition.wait(&m_mutex);
        componentStarted = true;
    }

    if (!isInterruptionRequested())
    {// 启动电压脉冲
        sysDebug("startTest(): voltage = %dV, pulseWidth = %dus, pulseInterval = %dms", voltage, pulseWidth, pulseInterval);
        connect(BllController::getInstance(), &BllController::pwdflwCheckResultSignal, this, &VoltageMeasurePrivate::onCommRespond);

        ComCmd cmd;
        cmd.type = CMD_TYPE::PWRCHK;
        cmd.value1 = qRound(voltage * gVoltRatio);
        cmd.value2 = pulseWidth;
        cmd.value3 = pulseInterval;

        QMutexLocker locker(&m_mutex);
        BllController::getInstance()->sendPortCmd(cmd);
        m_condition.wait(&m_mutex);
        voltMeasureStarted = true;
    }

    if (!isInterruptionRequested())
    {// 开始测量
        sysDebug("startTest(): %dms testing...", VOLTAGE_TESTING_TIMES);
        QMutexLocker locker(&m_mutex);
        m_condition.wait(&m_mutex, VOLTAGE_TESTING_TIMES);
    }

    if (componentStarted)
    {// 停止测量组件
        stopComponent();
    }

    if (voltMeasureStarted)
    {// 停止电压脉冲
        sysDebug("startTest(): test finished, requeste stop this test.");
        connect(BllController::getInstance(), &BllController::pwdflwCheckResultSignal, this, &VoltageMeasurePrivate::onCommRespond);

        ComCmd cmd;
        cmd.type = CMD_TYPE::PWRCHK;
        cmd.value1 = 0;
        cmd.value2 = 0;
        cmd.value3 = 0;

        QMutexLocker locker(&m_mutex);
        BllController::getInstance()->sendPortCmd(cmd);
        m_condition.wait(&m_mutex);
    }

    if (voltMeasureStarted)
    {// 等待放电装置恢复正常
        sysDebug("wait %dms power-device Reset...", VOLTAGE_RECOVERT_TIMES);
        QMutexLocker locker(&m_mutex);
        m_condition.wait(&m_mutex, VOLTAGE_RECOVERT_TIMES);
    }
}

void VoltageMeasurePrivate::onCommRespond(const HostReply &info)
{// 串口回调函数
    int errorCode = info.parameter.toInt();
    sysDebug("VoltageMeasurePrivate::onCommRespond(): ret=%d", errorCode);
    disconnect(BllController::getInstance(), &BllController::pwdflwCheckResultSignal, this, &VoltageMeasurePrivate::onCommRespond);

    if (errorCode)
    {// 测试失败，终止后续测试
        sysDebug("VoltageMeasure Test Failed, Start Interrupt follow-up Test.");
        UserLogger::error(info.message);
        requestInterruption();
    }

    m_condition.wakeAll();
}

void VoltageMeasurePrivate::onMeasureError(bool stopTest)
{// 测量组件回调函数
    sysDebug("VoltageMeasurePrivate::onMeasureError(): ret=%d", stopTest);
    if (stopTest)
    {// 组件打开失败，终止后续测试
        sysDebug("measure component Open Failed, Start Interrupt follow-up Test.");
        requestInterruption();
    }

    m_condition.wakeAll();
}

void VoltageMeasurePrivate::onMeasureResult(double voltage, double pulseWidth)
{
    sysDebug("onMeasureResult: m_type=%d, vlotage=%f, pulseWidth=%f", m_type, voltage, pulseWidth);

    if (Low == m_type)
    {
        m_voltTest->lowVolt.realValue = voltage;
        m_voltTest->lowPulseWidth.realValue = pulseWidth;
    }
    else if (Medium == m_type)
    {
        m_voltTest->mediumVolt.realValue = voltage;
        m_voltTest->mediumPulseWidth.realValue = pulseWidth;
    }
    else if (High == m_type)
    {
        m_voltTest->highVolt.realValue = voltage;
        m_voltTest->highPulseWidth.realValue = pulseWidth;
    }
}

void VoltageMeasurePrivate::run()
{
    sysDebug("Start VoltageMeasure.");
    createComponent();

    sysDebug("lowVolt Test Start...");
    emit progress(tr("lowVolt Test..."));
    startTest(m_voltTest->lowVolt.setValue, m_voltTest->lowPulseWidth.setValue);

    if (isInterruptionRequested())
    {
        sysDebug("Skip mediumVolt & highVolt Test.");
        emit progress(tr("lowVolt Test Failed."), true);
        destoryComponent();
        return;
    }

    m_type = Medium;
    sysDebug("mediumVolt Test Start...");
    emit progress(tr("mediumVolt Test..."));
    startTest(m_voltTest->mediumVolt.setValue, m_voltTest->mediumPulseWidth.setValue);

    if (isInterruptionRequested())
    {
        sysDebug("Skip highVolt Test.");
        emit progress(tr("mediumVolt Test Failed."), true);
        destoryComponent();
        return;
    }

    m_type = High;
    sysDebug("highVolt Test Start...");
    emit progress(tr("highVolt Test..."));
    startTest(m_voltTest->highVolt.setValue, m_voltTest->highPulseWidth.setValue);

    destoryComponent();
    sysDebug("VoltageMeasure Finished.");
    emit progress(tr("VoltageMeasure Finished"), true);
}

// 依托事件循环，必须在主线程中执行
void VoltageMeasurePrivate::initComponent()
{
    sysDebug("init measure component()");
    DataCenter::instance();
    ControlCenter::instance();
}

void VoltageMeasurePrivate::createComponent()
{
    sysDebug("create measure component.");

    // 示波器组件
    bllChartReader *chartReader = new bllChartReader(VOLTAGE_PULSE_INTERVAL);
    ControlCenter::instance()->addComponent(ComponentPtr(chartReader));

    // 计算组件
    MeasureWorker *measureWorker = new MeasureWorker(&m_vds);
    DataCenter::instance()->addComponent(ComponentPtr(measureWorker));

    connect(&m_vds, &VdsMeasure::measureError, this, &VoltageMeasurePrivate::onMeasureError);
    connect(&m_vds, &VdsMeasure::measureResult, this, &VoltageMeasurePrivate::onMeasureResult);
}

void VoltageMeasurePrivate::destoryComponent()
{
    sysDebug("destory measure component.");
    disconnect(&m_vds, &VdsMeasure::measureError, this, &VoltageMeasurePrivate::onMeasureError);
    disconnect(&m_vds, &VdsMeasure::measureResult, this, &VoltageMeasurePrivate::onMeasureResult);

    DataCenter::instance()->clearComponent();
    ControlCenter::instance()->clearComponent();
}

void VoltageMeasurePrivate::setVdsParameter(int voltage, int pulseWidth, int pulseInterval)
{
    VdsConfig().setParameter(voltage, pulseWidth, pulseInterval);
}

void VoltageMeasurePrivate::startComponent(int voltage, int pulseWidth, int pulseInterval)
{
    sysDebug("start measure component.");
    setVdsParameter(voltage, pulseWidth, pulseInterval);
    DataCenter::instance()->start();
    ControlCenter::instance()->start();
}

void VoltageMeasurePrivate::stopComponent()
{
    sysDebug("stop measure component.");
    DataCenter::instance()->stop();
    ControlCenter::instance()->stop();
}

#include "voltagemeasure.moc"
